#include "Server.h"
#include "Connection/Connection.h"
#include "Socket/SocketAddress.h"
#include "Threads/Threads.h"
#include "Utils/ByteArray.h"
#include "Messages/MessageLogIn.h"
#include "Messages/MessagesHandler.h"
#include "DataBase/DataBaseConnection.h"

#include "Utils/DebugLog.h"

#ifdef WIN32
#include <windows.h>
#endif




Server* Server::m_instance = NULL;

std::vector< Connection* >	Server::m_connections;
Socket*	Server::m_listenSocket = NULL;
Socket*	Server::m_policySocket = NULL;
bool Server::isActive = true;
bool Server::isConnectionsBusy = false;


//====================================================================
//
//
//====================================================================
#ifdef WIN32
static DWORD WINAPI thAcceptPolicy(LPVOID arg)
#else
static void* thAcceptPolicy(void* arg)
#endif
{
	while(Server::isActive)
	{
		if(Server::getPolicySocket()->Select(Socket::SELECT_READ))
		{
			Socket *sd = Server::getPolicySocket()->Accept();
			if(sd != NULL)
			{
				Server::sendPolicy(sd);
			}
		}
		Sleep(300); // --HACK, 
	}

	return 0;
}

//====================================================================
//
//
//====================================================================
void Server::sendPolicy(Socket* socket)
{
	// Send security policy
	char buff[512];
	socket->Recv(buff);
	if(strstr(buff, "<policy-file-request/>") != 0)
	{
		printf("%s\n", buff);
		char policy[] = "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";
		int len = sizeof(policy);
		socket->Send(policy, len);
		socket->Disconnect();
	}
}

//====================================================================
//
//
//====================================================================
Server::Server()
{
	m_listenSocket = new Socket(Socket::SOCKET_TCP, "", SERVER_LISTEN_PORT);
	m_listenSocket->NonBlock();
	m_listenSocket->Listen();

	m_policySocket = new Socket(Socket::SOCKET_TCP, "", SERVER_POLICY_PORT);
	m_policySocket->NonBlock();
	m_policySocket->Listen();
}

//====================================================================
//
//
//====================================================================
Server::~Server()
{
	for(unsigned int i = 0; i < m_connections.size(); ++i)
	{
		delete m_connections[i];
	}
	m_connections.clear();

	if(m_listenSocket != NULL)
	{
		delete m_listenSocket;
		m_listenSocket = NULL;
	}

	if(m_policySocket != NULL)
	{
		delete m_policySocket;
		m_policySocket = NULL;
	}
}

//====================================================================
//
//
//====================================================================
Server* Server::getInstance()
{
	if(!m_instance)
	{
		m_instance = new Server();
	}

	return m_instance;
}

//====================================================================
//
//
//====================================================================
void Server::start()
{	
	printf("Server::start - server is started\n");

	Threads::New(thAcceptPolicy, NULL);
	DataBaseConnection::getInstance()->connect();
}

//====================================================================
//
//
//====================================================================
void Server::update()
{	
	if(!Server::isActive) return;

	if(m_listenSocket->Select(Socket::SELECT_READ))
	{
		Socket *sd = m_listenSocket->Accept();
		if(sd != NULL)
		{
			printf("Server::update - add new connection %s:%d\n", sd->getAddress()->getIp(), sd->getAddress()->getPort());
			m_connections.push_back(new Connection(sd));
			sd->NonBlock();
		}
	}

	for(int i = 0; i < (int)m_connections.size(); ++i)
	{
		Connection *conn = m_connections[i];

		if(conn->getSocket()->Select(Socket::SELECT_READ))
		{
			if(conn->getSocket()->recvByteArray() > 0)
			{
				conn->getSocket()->getBuffer()->seekBegin();
				MessagesHandler::getInstance()->createMessage(conn->getSocket()->getBuffer(), true, conn);
				conn->getSocket()->getBuffer()->seekEnd();
			}
		}
		if(conn->getSocket()->Select(Socket::SELECT_WRITE))
		{
			conn->sendFirstPendingMessage();
		}
	
		if(!conn->getSocket()->isAlive())
		{
			MessagesHandler::getInstance()->addUnloginMsg(conn);

			printf("Server::update - close connection:  %s:%d\n", conn->getSocket()->getAddress()->getIp(), conn->getSocket()->getAddress()->getPort());
			delete conn;
			m_connections.erase(m_connections.begin() + i);
			i--;
		}
	}
}
